
package net.qiqbframework.messaging;


import net.qiqbframework.serialization.SerializedObject;
import net.qiqbframework.serialization.Serializer;

import javax.annotation.Nonnull;
import java.util.Map;

public abstract class MessageDecorator<T> implements Message<T> {

    private final Message<T> delegate;

    /**
     * Initializes a new decorator with given {@code delegate} message. The decorator delegates to the delegate for
     * the message's payload, metadata and identifier.
     *
     * @param delegate the message delegate
     */
    protected MessageDecorator(Message<T> delegate) {
        this.delegate = delegate;
    }

    @Override
    public String getIdentifier() {
        return delegate.getIdentifier();
    }

    @Override
    public MetaData getMetaData() {
        return delegate.getMetaData();
    }

    @Override
    public T getPayload() {
        return delegate.getPayload();
    }

    @Override
    public Class<T> getPayloadType() {
        return delegate.getPayloadType();
    }

    @Override
    public <S> SerializedObject<S> serializePayload(Serializer serializer, Class<S> expectedRepresentation) {
        return delegate.serializePayload(serializer, expectedRepresentation);
    }

    @Override
    public <S> SerializedObject<S> serializeMetaData(Serializer serializer, Class<S> expectedRepresentation) {
        return delegate.serializeMetaData(serializer, expectedRepresentation);
    }

    @Override
    public void andMetaData(@Nonnull Map<String, ?> metaData) {
        delegate.andMetaData(metaData);
    }

    @Override
    public void withMetaData(@Nonnull Map<String, ?> metaData) {
        delegate.withMetaData(metaData);
    }

    protected Message<T> getDelegate() {
        return delegate;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder()
                .append(describeType())
                .append("{");
        describeTo(sb);
        return sb.append("}")
                .toString();
    }


    protected void describeTo(StringBuilder stringBuilder) {
        stringBuilder.append("payload={")
                .append(getPayload())
                .append('}')
                .append(", metadata={")
                .append(getMetaData())
                .append('}')
                .append(", messageIdentifier='")
                .append(getIdentifier())
                .append('\'');
    }

    protected String describeType() {
        return getClass().getSimpleName();
    }
}
